package com.coincalf.web;

import com.alibaba.fastjson.JSONObject;
import com.coincalf.chan.feign.MessagingServiceClient;
import com.coincalf.dto.AutoOrderDto;
import com.coincalf.dto.CreateTradeOrderDTO;
import com.coincalf.entity.Market;
import com.coincalf.framework.constants.Constant;
import com.coincalf.framework.http.Response;
import com.coincalf.framework.utils.SignUtil;
import com.coincalf.service.ConfigService;
import com.coincalf.service.EntrustOrderService;
import com.coincalf.service.MarketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;

@Slf4j
@RestController
@RequestMapping("/autoOrder")
public class AutomaticOrderController {


    @Autowired
    private ConfigService configService;
    @Autowired
    private MarketService marketService;
    @Autowired
    private EntrustOrderService entrustOrderService;
    @Autowired
    private MessagingServiceClient messagingServiceClient;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;


    /**
     * 币币交易刷单
     *
     * @return
     */
    @PostMapping("/coinOrder")
    public boolean autoOrder(@RequestBody AutoOrderDto autoOrderDto) {
        if (StringUtils.isEmpty(autoOrderDto.getSymbol()) || StringUtils.isEmpty(autoOrderDto.getCurrentTime()) || StringUtils.isEmpty(autoOrderDto.getRandomNum()) || StringUtils.isEmpty(autoOrderDto.getSign())) {
            log.warn("请求参数不能为空");
            return false;
        }
        boolean b = SignUtil.verifySign(autoOrderDto.getCurrentTime(), autoOrderDto.getRandomNum(), autoOrderDto.getSign());
        if (!b) {
            log.warn("签名验证失败");
            return false;
        }
        //Config config = configService.queryByTypeAndCode(Constant.CONFIG_TYPE_SYSTEM, Constant.ROBOT_SWIPE);
        //if (config != null && config.getValue().equals("1")) {
        Market market = marketService.queryBySymbol(autoOrderDto.getSymbol());
        if (market == null) {
            log.warn("币币交易机器人刷单，交易市场错误 symbol={}", autoOrderDto.getSymbol());
            return false;
        }
        // TODO: 机器人userId 暂时写死 后续修改到数据库获取
        long userId = 999999999999999999L;
        BigDecimal entrustOrderPrice;

        /**
         * 下单价格取决于当前价格
         */
        //TODO redisKeyAqsCurrentPrice修改
        String redisKeyCurrentPrice;
        if (autoOrderDto.getSymbol().equalsIgnoreCase("AQSUSDT")) {
            redisKeyCurrentPrice = "current:price:aqs";
        } else {
            redisKeyCurrentPrice = "current:price:aqp";
        }
        BigDecimal price = (BigDecimal) redisTemplate.opsForValue().get(redisKeyCurrentPrice);
        if (price != null) {
            entrustOrderPrice = price.multiply(AutomaticOrderController.entrustOrderPrice2().divide(BigDecimal.valueOf(10000), 4, RoundingMode.DOWN));
        } else {
            log.warn("币币交易机器人刷单，暂未设置交易对价格 symbol={}", autoOrderDto.getSymbol());
            return false;
        }

        /**
         * TODO 获取买一价格 卖一价格
         */
        /*BigDecimal buyFirstPrice = entrustOrderService.selectBuyFirstPrice(market.getId());
        BigDecimal sellFirstPrice = entrustOrderService.selectSellFirstPrice(market.getId());
        if (buyFirstPrice == null && sellFirstPrice == null) {
            log.info("没有人挂单买卖");
            //没有人挂单买卖 则根据当前价格进行刷单
            String redisKeyAqsCurrentPrice = "current:price:aqs";
            BigDecimal price = (BigDecimal) redisTemplate.opsForValue().get(redisKeyAqsCurrentPrice);
            if (price != null) {
                entrustOrderPrice = price.multiply(AutomaticOrderController.entrustOrderPrice().divide(BigDecimal.valueOf(10000), 4, RoundingMode.DOWN));
            } else {
                log.warn("币币交易机器人刷单，暂未设置交易对价格 symbol={}", autoOrderDto.getSymbol());
                return false;
            }
        } else if (buyFirstPrice != null && sellFirstPrice != null) {
            log.info("买卖单均有人挂 buyPrice={} sellPrice={}", buyFirstPrice, sellFirstPrice);
            //买卖单均有人挂
            if (buyFirstPrice.compareTo(sellFirstPrice) > 0) {
                log.warn("币币交易机器人刷单，存在未撮合订单，暂时不处理 symbol={}", autoOrderDto.getSymbol());
                return false;
            }
            //取买一卖一之间价格进行刷单
            entrustOrderPrice = buyFirstPrice.add(sellFirstPrice).divide(BigDecimal.valueOf(2), 8, RoundingMode.DOWN);
            if (entrustOrderPrice.compareTo(buyFirstPrice) == 0) {
                entrustOrderPrice = entrustOrderPrice.multiply(new BigDecimal("0.008"));
            }
        } else if (buyFirstPrice == null) {
            log.info("只有人挂卖单");
            //只有人挂卖单 刷单价格必须小于等于委托中卖单
            String redisKeyAqsCurrentPrice = "current:price:aqs";
            BigDecimal price = (BigDecimal) redisTemplate.opsForValue().get(redisKeyAqsCurrentPrice);
            if (price != null) {
                entrustOrderPrice = price.multiply(AutomaticOrderController.entrustOrderPrice().divide(BigDecimal.valueOf(10000), 4, RoundingMode.DOWN));
                if (entrustOrderPrice.compareTo(sellFirstPrice) > 0) {
                    entrustOrderPrice = sellFirstPrice.multiply(new BigDecimal("0.996"));
                }
            } else {
                log.warn("币币交易机器人刷单，暂未设置交易对价格 symbol={}", autoOrderDto.getSymbol());
                return false;
            }
        } else {
            log.info("只有人挂买单");
            //只有人挂买单 刷单价格必须大于等于委托中买单
            String redisKeyAqsCurrentPrice = "current:price:aqs";
            BigDecimal price = (BigDecimal) redisTemplate.opsForValue().get(redisKeyAqsCurrentPrice);
            if (price != null) {
                entrustOrderPrice = price.multiply(AutomaticOrderController.entrustOrderPrice().divide(BigDecimal.valueOf(10000), 4, RoundingMode.DOWN));
                if (entrustOrderPrice.compareTo(buyFirstPrice) > 0) {
                    entrustOrderPrice = buyFirstPrice.multiply(new BigDecimal("1.004"));
                }
            } else {
                log.warn("币币交易机器人刷单，暂未设置交易对价格 symbol={}", autoOrderDto.getSymbol());
                return false;
            }
        }*/

        //TODO 刷单数量  需要大于等于最小下单数量 从数据库获取 暂时写死
        BigDecimal amount = AutomaticOrderController.randomAmount();
        log.info("本次刷单委托价格={}", entrustOrderPrice);
        //下买单
        this.entrustOrder(userId, autoOrderDto.getSymbol(), amount, 1, entrustOrderPrice, market);
        //下卖单
        this.entrustOrder(userId, autoOrderDto.getSymbol(), amount, 2, entrustOrderPrice, market);
        return true;
    }

    public void entrustOrder(long userId, String symbol, BigDecimal amount, Integer type, BigDecimal price, Market market) {
        CreateTradeOrderDTO order = new CreateTradeOrderDTO();
        order.setSymbol(symbol);
        order.setVolume(amount);
        order.setType(type);
        order.setPrice(price);
        order.setPriceType(2);

        Response response = entrustOrderService.createEntrustOrder(market, order, userId);
        if (response.getData() == null) {
            log.warn("机器人刷单任务下单失败");
            return;
        }

        long orderId = Long.parseLong(response.getData().toString());
        // 将委托订单加入撮合队列
        String redisKey = new StringBuffer(Constant.REDIS_KEY_TRADE_MATCH).append(order.getSymbol()).toString();
        redisTemplate.opsForList().rightPush(redisKey, orderId);
        // 更新委托队列-默认合并深度
        entrustOrderService.DEPTH_CACHE_INSTANCE().refresh(market.getId());
        // 更新委托队列-合并深度1
        entrustOrderService.MERGE_LOW_DEPTH_CACHE_INSTANCE().refresh(market.getId());
        // 更新委托队列-合并深度2
        entrustOrderService.MERGE_HIGH_DEPTH_CACHE_INSTANCE().refresh(market.getId());
        // 推送用户未成交委托
        JSONObject body = new JSONObject();
        body.put("symbol", order.getSymbol());
        messagingServiceClient.convertAndSendToUser(Constant.CH_ORDER_PENDING, String.valueOf(userId), body.toJSONString());
    }

    private static BigDecimal randomAmount() {
        return BigDecimal.valueOf(new Random().nextInt(6)).add(BigDecimal.valueOf(10));
    }

    //生成随机数 0.98-1.02
    private static BigDecimal entrustOrderPrice() {
        return new BigDecimal(9800 + Math.random() * (10200 - 9800 + 1));
    }

    //生成随机数 1-1.02
    private static BigDecimal entrustOrderPrice2() {
        return new BigDecimal(10000 + Math.random() * 201);
    }

}
